Skip to content

fix(flow-chat): centre single-line user messages in their bubble - #1953

Merged
bobleer merged 1 commit into
GCWing:mainfrom
bobleer:fix/user-message-single-line-centering
Aug 1, 2026
Merged

fix(flow-chat): centre single-line user messages in their bubble#1953
bobleer merged 1 commit into
GCWing:mainfrom
bobleer:fix/user-message-single-line-centering

Conversation

@bobleer

@bobleer bobleer commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

A user message that fits on one line renders with its text sitting above the bubble's vertical centre. This centres it by stopping the idle action buttons from inflating the row.

The action cluster (copy / edit / rollback) keeps its 28px layout box while idle at opacity: 0 — opacity hides the buttons but does not remove their layout box. That made the cluster taller than the ~22px first-line box and therefore the tallest item in .user-message-item__main, whose align-items: flex-start then pinned a single-line message to the top of an over-tall row.

Type and Areas

Type: bug fix (UI/UX)

Areas: web UI (flow_chat — user message bubble)

Motivation / Impact

Single-line messages such as 继续 looked visibly off-centre: 8.36px of space above the text against 14.24px below it, inside a bubble whose padding is a symmetric 0.46rem. Multi-line messages never showed the problem, because two lines of text (44.23px) already exceed the 28px cluster and the text was driving the row height again — which is why this only reproduced on short messages.

The fix collapses the action cluster to the first-line box, so the text drives the row height and the bubble's symmetric padding is restored. Hit-target size is unchanged (still 28px); the cluster simply stops contributing extra height. The line box is derived from the existing typography tokens rather than hardcoded, so the correction follows the user's font-size preference in both directions.

Two related improvements come along with it:

  • The action buttons are now centred on the first text line; they were previously 2.94px low.
  • The --failed variant already applied this idea but only as a margin-top, leaving a residual 2.33px offset. It now re-points the shared --user-message-line-box variable and reuses the base rule.

Worth noting as corroboration: the image-export path already excludes .user-message-item__actions from the render (ExportImageButton.tsx), so exported conversation images were already tight and centred. The live UI was the odd one out.

Verification

Measured in-browser against the real compiled stylesheet — UserMessageItem.scss and the apply-design-tokens mixin compiled together with sass, then applied to the component's real DOM structure — rather than reasoning from the source. "Before" was produced by neutralising only the new margins on that same page.

Metric (single-line message) Before After
Bubble height 44.72px 38.84px
Space above text 8.36px 8.36px
Space below text 14.24px 8.37px
Text offset from bubble centre −2.94px 0
Button centre vs first-line centre −2.94px 0
Two-line / three-line bubble height 60.95 / 83.07px 60.95 / 83.07px (unchanged)

Also checked with the fix applied: buttons stay inside the bubble (5.42px clearance top and bottom, no clipping), and the pending-steering tag and timestamp variants remain correctly aligned.

Commands run:

  • pnpm run type-check:web — passes
  • pnpm exec vitest run src/flow_chat/components/modern src/app/startup/startupPerformanceContract.test.ts — 27 files, 260 tests, all passing
  • node scripts/audit-theme-colors.mjs — exit 0
  • node scripts/validate-theme-visual-contract.mjs — 10/10 required surfaces covered

Reviewer Notes

CSS-only change; no component, markup, or behaviour changes. No new colours, so the theme governance baselines are untouched.

The formula calc((var(--user-message-line-box) - 28px) / 2) is deliberately signed: if a larger font preference makes the line box exceed 28px, the margins turn positive and the cluster still matches the first-line box exactly, so the centring holds in both directions.

AI-assisted change. Testing level: fully tested for the layout behaviour it targets (measured before/after plus the focused suites above); not exercised in a running desktop session.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable. (None affected — CSS only.)

The action cluster keeps its 28px layout box while idle at `opacity: 0`,
so it outgrew the ~22px first-line box and became the tallest item in the
flex row. With `align-items: flex-start` that pinned a single-line message
to the top of an over-tall row, leaving 14.24px below the text against
8.36px above it, and the text read as sitting above the bubble's centre.

- collapse the action cluster to the first-line box so the text drives the
  row height and the bubble's symmetric vertical padding is restored
- centre the buttons on the first line (previously 2.94px low)
- derive the line box from the existing typography tokens so the fix
  follows the user's font-size preference
- fold the `--failed` variant's one-sided margin into the shared rule,
  which also removes its residual 2.33px offset

Multi-line messages are unaffected: their text already exceeded the
cluster height, so bubble heights there are unchanged.
@bobleer
bobleer merged commit d158dd8 into GCWing:main Aug 1, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant